<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>电商平台 - 用户账号管理</title>
    <!-- 引入外部资源 -->
    <script src="https://cdn.tailwindcss.com"></script>
    <link href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css" rel="stylesheet">
    <link rel="stylesheet" type="text/css" href="./css/top-nav-optimized.css"/>
    <script src="https://cdn.jsdelivr.net/npm/axios@1.6.8/dist/axios.min.js"></script>
    <!-- 1. 先引入 axios（util 中的网络请求依赖它） -->
    <script src="./js/axios.min.js"></script>
    <!-- 2. 再引入该工具脚本（定义 util 和 axios 配置） -->
    <script src="./js/common.js"></script>
    <!-- 3. 再引入 Vue（<top> 组件依赖 Vue） -->
    <script src="./js/vue.js"></script>

    <!-- Tailwind 配置 -->
    <script>
        tailwind.config = {
            theme: {
                extend: {
                    colors: {
                        primary: '#165DFF',       // 主色调（蓝色，与登录页保持一致）
                        success: '#00B42A',       // 成功色（绿色）
                        warning: '#FF7D00',       // 警告色（橙色）
                        danger: '#F53F3F',        // 危险色（红色）
                        gray: {
                            100: '#F2F3F5',
                            200: '#E5E6EB',
                            300: '#C9CDD4',
                            400: '#86909C',
                            500: '#4E5969',
                            600: '#272E3B',
                            700: '#1D2129',
                        }
                    },
                    fontFamily: {
                        sans: ['Inter', 'system-ui', 'sans-serif'],
                    },
                    boxShadow: {
                        'card': '0 2px 8px 0 rgba(0, 0, 0, 0.08)',
                        'dropdown': '0 4px 16px 0 rgba(0, 0, 0, 0.08)',
                    }
                },
            }
        }
    </script>

    <!-- 自定义工具类 -->
    <style type="text/tailwindcss">
        @layer utilities {
            .content-auto {
                content-visibility: auto;
            }
            .transition-all-200 {
                transition: all 0.2s ease;
            }
            .table-hover {
                @apply hover:bg-gray-100 transition-all-200;
            }
            .btn-primary {
                @apply bg-primary text-white px-4 py-2 rounded-md hover:bg-primary/90 transition-all-200;
            }
            .btn-outline {
                @apply border border-gray-300 px-4 py-2 rounded-md hover:bg-gray-100 transition-all-200;
            }
            .btn-danger {
                @apply bg-danger text-white px-4 py-2 rounded-md hover:bg-danger/90 transition-all-200;
            }
            .input-style {
                @apply border border-gray-300 rounded-md px-3 py-2 focus:outline-none focus:ring-2 focus:ring-primary/30 focus:border-primary transition-all-200;
            }
        }
    </style>

    <style>
        /* 基础样式重置 */
        body {
            font-family: 'Inter', system-ui, sans-serif;
            background-color: #F7F8FA;
        }
        /* 滚动条美化 */
        ::-webkit-scrollbar {
            width: 6px;
            height: 6px;
        }
        ::-webkit-scrollbar-thumb {
            background-color: #C9CDD4;
            border-radius: 3px;
        }
        ::-webkit-scrollbar-track {
            background-color: #F2F3F5;
        }
        /* 侧边栏固定定位（桌面端） */
        @media (min-width: 1024px) {
            .sidebar {
                position: fixed;
                top: 0;
                left: 0;
                height: 100vh;
                width: 220px;
                z-index: 100;
            }
            .main-content {
                margin-left: 220px;
            }
        }
        /* 移动端适配 */
        @media (max-width: 1023px) {
            .sidebar {
                position: fixed;
                top: 0;
                left: -220px;
                height: 100vh;
                width: 220px;
                z-index: 999;
                transition: left 0.3s ease;
            }
            .sidebar.show {
                left: 0;
            }
            .overlay {
                position: fixed;
                top: 0;
                left: 0;
                right: 0;
                bottom: 0;
                background-color: rgba(0, 0, 0, 0.5);
                z-index: 998;
                display: none;
            }
            .overlay.show {
                display: block;
            }
        }
    </style>
</head>
<body>
<div id="app" class="flex h-screen overflow-hidden">
    <!-- 侧边导航栏 -->
    <div class="sidebar bg-white shadow-md flex flex-col">
        <!-- 系统Logo -->
        <div class="h-16 flex items-center justify-center border-b border-gray-200">
            <h1 class="text-primary font-bold text-xl">ShopEasy 管理系统</h1>
        </div>
        <!-- 导航菜单 - 移除了订单管理 -->
        <div class="flex-1 overflow-y-auto py-4">
            <ul>
                <li class="mb-1">
                    <a href="#" class="flex items-center px-4 py-3 text-gray-500 hover:bg-primary/5 hover:text-primary transition-all-200">
                        <i class="fa fa-tachometer w-6 text-center"></i>
                        <span class="ml-2">控制台首页</span>
                    </a>
                </li>
                <!-- 当前选中：用户管理 -->
                <li class="mb-1">
                    <a href="#" class="flex items-center px-4 py-3 bg-primary/10 text-primary font-medium transition-all-200">
                        <i class="fa fa-users w-6 text-center"></i>
                        <span class="ml-2">用户账号管理</span>
                    </a>
                </li>
                <li class="mb-1">
                    <a href="./admin_role.html" class="flex items-center px-4 py-3 text-gray-500 hover:bg-primary/5 hover:text-primary transition-all-200">
                        <i class="fa fa-shield w-6 text-center"></i>
                        <span class="ml-2">角色管理</span>
                    </a>
                </li>
            </ul>
        </div>
        <!-- 用户信息 -->
        <div class="p-4 border-t border-gray-200">
            <div class="flex items-center">
                <img src="https://picsum.photos/40/40" alt="管理员头像" class="w-8 h-8 rounded-full">
                <div class="ml-3">
                    <p class="text-sm font-medium text-gray-700">admin</p>
                    <p class="text-xs text-gray-400">管理员</p>
                </div>
                <!-- 修复后按钮（删除a标签，直接在按钮内放图标） -->
                <a href="./index.html"><button class="text-gray-600 hover:text-danger transition-colors" onclick="util.logout()">
                    <span class="ml-1">退出登录</span>
                    <i class="fa fa-sign-out"></i>
                </button></a>
            </div>
        </div>
    </div>

    <!-- 移动端遮罩层 -->
    <div class="overlay" @click="toggleSidebar"></div>

    <!-- 主内容区 -->
    <div class="main-content flex flex-col overflow-hidden">
        <!-- 顶部导航栏 -->
        <header class="h-16 bg-white shadow-sm flex items-center justify-between px-6">
            <!-- 移动端菜单按钮 -->
            <button class="md:hidden text-gray-500 hover:text-primary transition-all-200" @click="toggleSidebar">
                <i class="fa fa-bars text-xl"></i>
            </button>
            <!-- 面包屑导航（桌面端） -->
            <div class="hidden md:flex items-center text-sm text-gray-500">
                <a href="/index.html" class="hover:text-primary transition-all-200">首页</a>
                <i class="fa fa-angle-right mx-2 text-gray-300"></i>
                <span class="text-gray-700">用户账号管理</span>
            </div>
            <!-- 右侧功能按钮 -->
            <div class="flex items-center space-x-4">
                <button class="text-gray-500 hover:text-primary transition-all-200 relative">
                    <i class="fa fa-bell text-xl"></i>
                    <span class="absolute top-0 right-0 w-2 h-2 bg-danger rounded-full"></span>
                </button>
                <button class="text-gray-500 hover:text-primary transition-all-200">
                    <i class="fa fa-question-circle text-xl"></i>
                </button>
            </div>
        </header>

        <!-- 内容区域 -->
        <main class="flex-1 overflow-y-auto p-6">
            <!-- 页面标题与操作按钮 -->
            <div class="flex flex-col md:flex-row md:items-center md:justify-between mb-6">
                <div>
                    <h2 class="text-[clamp(1.25rem,3vw,1.5rem)] font-bold text-gray-700">用户账号管理</h2>
                    <p class="text-sm text-gray-400 mt-1">管理系统用户账号、角色分配及状态控制</p>
                </div>
                <button class="btn-primary mt-4 md:mt-0 flex items-center" @click="showAddUserModal">
                    <i class="fa fa-plus mr-2"></i>
                    <span>新增用户</span>
                </button>
            </div>

            <!-- 搜索与筛选栏 -->
            <div class="bg-white rounded-lg shadow-card p-4 mb-6">
                <div class="grid grid-cols-1 md:grid-cols-4 gap-4">
                    <!-- 用户名搜索 -->
                    <div>
                        <label class="block text-sm font-medium text-gray-700 mb-1">用户名:</label>
                        <div class="relative">

                            <input
                                    type="text"
                                    v-model="searchForm.username"
                                    placeholder="请输入用户名"
                                    class="input-style pl-5 w-full"
                            >
                        </div>
                    </div>
                    <!-- 手机号搜索 -->
                    <div>
                        <label class="block text-sm font-medium text-gray-700 mb-1">手机号:</label>
                        <div class="relative">

                            <input
                                    type="text"
                                    v-model="searchForm.phone"
                                    placeholder="请输入手机号"
                                    class="input-style pl-10 w-full"
                            >
                        </div>
                    </div>
                    <!-- 用户状态筛选 -->
                    <div>
                        <label class="block text-sm font-medium text-gray-700 mb-1">用户状态</label>
                        <select v-model="searchForm.status" class="input-style w-full">
                            <option value="">全部状态</option>
                            <option value="1">正常</option>
                            <option value="0">冻结</option>
                        </select>
                    </div>
                    <!-- 角色筛选 -->
                    <div>
                        <label class="block text-sm font-medium text-gray-700 mb-1">所属角色</label>
                        <select v-model="searchForm.roleId" class="input-style w-full">
                            <option value="">全部角色</option>
                            <option v-for="role in roleList" :key="role.roleId" :value="role.roleId">
                                {{ role.roleName }}
                            </option>
                        </select>
                    </div>
                </div>
                <!-- 搜索按钮 -->
                <div class="flex justify-end mt-4 space-x-3">
                    <button class="btn-outline" @click="resetSearch">
                        <i class="fa fa-refresh mr-1"></i> 重置
                    </button>
                    <button class="btn-primary" @click="fetchUserList">
                        <i class="fa fa-search mr-1"></i> 搜索
                    </button>
                </div>
            </div>

            <!-- 用户列表 -->
            <div class="bg-white rounded-lg shadow-card overflow-hidden">
                <!-- 列表操作栏 -->
                <div class="p-4 border-b border-gray-200 flex flex-col sm:flex-row sm:items-center sm:justify-between">
                    <div class="flex items-center">
                        <input
                                type="checkbox"
                                v-model="selectAll"
                                class="h-4 w-4 text-primary border-gray-300 rounded"
                                @change="handleSelectAll"
                        >
                        <label class="ml-2 text-sm text-gray-700">全选</label>
                        <span class="ml-3 text-sm text-gray-500">已选 {{ selectedUserIds.length }} 项</span>
                    </div>
                    <!-- 批量操作按钮（仅选中时显示） -->
                    <div class="flex space-x-3 mt-3 sm:mt-0" v-if="selectedUserIds.length > 0">
                        <button class="btn-outline text-gray-500" @click="batchFreeze">
                            <i class="fa fa-lock mr-1"></i> 批量冻结
                        </button>
                        <button class="btn-danger" @click="batchDelete">
                            <i class="fa fa-trash mr-1"></i> 批量删除
                        </button>
                    </div>
                </div>

                <!-- 表格 -->
                <div class="overflow-x-auto">
                    <table class="w-full">
                        <thead>
                        <tr class="bg-gray-50 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
                            <th class="px-6 py-3 w-12">
                                <input
                                        type="checkbox"
                                        v-model="selectAll"
                                        class="h-4 w-4 text-primary border-gray-300 rounded"
                                        @change="handleSelectAll"
                                >
                            </th>
                            <th class="px-6 py-3">用户名</th>
                            <th class="px-6 py-3">手机号</th>
                            <th class="px-6 py-3">角色</th>
                            <th class="px-6 py-3">余额</th>
                            <th class="px-6 py-3">创建时间</th>
                            <th class="px-6 py-3">状态</th>
                        </tr>
                        </thead>
                        <tbody class="bg-white divide-y divide-gray-200">
                        <!-- 数据行 - 实际项目中由后端数据填充 -->
                        <tr class="table-hover" v-for="user in userList" :key="user.id">
                            <td class="px-6 py-4">
                                <input
                                        type="checkbox"
                                        :value="user.id"
                                        v-model="selectedUserIds"
                                        class="h-4 w-4 text-primary border-gray-300 rounded"
                                >
                            </td>
                            <!--                            <td class="px-6 py-4 text-sm text-gray-700">{{ user.id }}</td>-->
                            <td class="px-6 py-4">
                                <div class="flex items-center">
                                    <img :src="`https://picsum.photos/40/40?user=${user.id}`" alt="用户头像" class="w-8 h-8 rounded-full">
                                    <span class="ml-3 text-sm font-medium text-gray-700">{{ user.username }}</span>
                                </div>
                            </td>
                            <td class="px-6 py-4 text-sm text-gray-500">{{ user.phone || '-' }}</td>
                            <td class="px-6 py-4">
                                        <span
                                                class="inline-block px-2 py-1 text-xs rounded-full bg-primary/10 text-primary mr-1 mb-1"
                                        >
                                            {{ user.roleName }}
                                        </span>
                            </td>
                            <td class="px-6 py-4 text-sm text-gray-700">¥{{ (user.balance / 100).toFixed(2) }}</td>
                            <td class="px-6 py-4 text-sm text-gray-500">{{ formatTime(user.createTime) }}</td>
                            <td class="px-6 py-4">
                                        <span v-if="user.status === 1" class="px-2 py-1 text-xs rounded-full bg-success/10 text-success">
                                            正常
                                        </span>
                                <span v-else class="px-2 py-1 text-xs rounded-full bg-danger/10 text-danger">
                                            冻结
                                        </span>
                            </td>
                            <td class="px-6 py-4 text-right text-sm font-medium">
                                <button
                                        class="text-primary hover:text-primary/80 mr-4 transition-all-200"
                                        @click="showEditUserModal(user)"
                                >
                                    编辑
                                </button>
                                <button
                                        class="text-warning hover:text-warning/80 mr-4 transition-all-200"
                                        @click="openAssignRoleModal(user)"
                                >
                                    分配角色
                                </button>
                                <button
                                        v-if="user.status === 1"
                                        class="text-danger hover:text-danger/80 transition-all-200"
                                        @click="handleFreezeUser(user.id)"
                                >
                                    冻结
                                </button>
                                <button
                                        v-else
                                        class="text-success hover:text-success/80 transition-all-200"
                                        @click="handleUnfreezeUser(user.id)"
                                >
                                    解冻
                                </button>
                            </td>
                        </tr>
                        <!-- 空数据提示 -->
                        <tr v-if="userList.length === 0">
                            <td colspan="9" class="px-6 py-12 text-center">
                                <div class="flex flex-col items-center">
                                    <img src="https://picsum.photos/120/120?empty=1" alt="暂无数据" class="w-24 h-24 mb-4 opacity-50">
                                    <p class="text-gray-500">暂无用户数据</p>
                                    <button class="mt-4 btn-outline" @click="fetchUserList">
                                        <i class="fa fa-refresh mr-1"></i> 刷新
                                    </button>
                                </div>
                            </td>
                        </tr>
                        </tbody>
                    </table>
                </div>

                <!-- 分页控件 -->
                <div class="px-6 py-4 border-t border-gray-200 flex flex-col sm:flex-row sm:items-center sm:justify-between">
                    <div class="text-sm text-gray-500 mb-4 sm:mb-0">
                        显示 {{ (currentPage - 1) * pageSize + 1 }} 到 {{ Math.min(currentPage * pageSize, totalCount) }} 条，共 {{ totalCount }} 条
                    </div>
                    <div class="flex items-center space-x-2">
                        <button
                                class="btn-outline px-3 py-1 text-sm"
                                :disabled="currentPage === 1"
                                @click="currentPage--"
                        >
                            <i class="fa fa-angle-left"></i>
                        </button>
                        <button
                                v-for="page in pageRange"
                                :key="page"
                                class="w-8 h-8 flex items-center justify-center rounded-md text-sm"
                                :class="currentPage === page ? 'bg-primary text-white' : 'border border-gray-300 text-gray-700 hover:bg-gray-100'"
                                @click="currentPage = page"
                        >
                            {{ page }}
                        </button>
                        <button
                                class="btn-outline px-3 py-1 text-sm"
                                :disabled="currentPage === totalPages"
                                @click="currentPage++"
                        >
                            <i class="fa fa-angle-right"></i>
                        </button>
                        <div class="flex items-center ml-4">
                            <span class="text-sm text-gray-500 mr-2">每页显示：</span>
                            <select
                                    v-model="pageSize"
                                    class="input-style w-20 text-sm px-2 py-1"
                                    @change="fetchUserList"
                            >
                                <option value="10">10条</option>
                                <option value="20">20条</option>
                                <option value="50">50条</option>
                                <option value="100">100条</option>
                            </select>
                        </div>
                    </div>
                </div>
            </div>
        </main>
    </div>

    <!-- 1. 新增用户弹窗 -->
    <div class="fixed top-0 left-0 right-0 bottom-0 flex items-center justify-center z-50" v-if="showAddModal">
        <div class="absolute inset-0 bg-black/50" @click="closeAddModal"></div>
        <div class="relative bg-white rounded-lg shadow-lg w-full max-w-md mx-4">
            <div class="p-4 border-b border-gray-200 flex items-center justify-between">
                <h3 class="font-bold text-lg text-gray-700">新增用户</h3>
                <button class="text-gray-400 hover:text-gray-700 transition-all-200" @click="closeAddModal">
                    <i class="fa fa-times"></i>
                </button>
            </div>
            <form class="p-6 space-y-4" @submit.prevent="handleAddUser">
                <div>
                    <label class="block text-sm font-medium text-gray-700 mb-1">用户名 <span class="text-danger">*</span></label>
                    <input
                            type="text"
                            v-model="addUserForm.username"
                            placeholder="请输入用户名（3-20位字符）"
                            class="input-style w-full"
                            required
                    >
                </div>
                <div>
                    <label class="block text-sm font-medium text-gray-700 mb-1">密码 <span class="text-danger">*</span></label>
                    <input
                            type="password"
                            v-model="addUserForm.password"
                            placeholder="请输入密码（6-20位字符）"
                            class="input-style w-full"
                            required
                    >
                </div>
                <div>
                    <label class="block text-sm font-medium text-gray-700 mb-1">手机号</label>
                    <input
                            type="tel"
                            v-model="addUserForm.phone"
                            placeholder="请输入手机号"
                            class="input-style w-full"
                            pattern="1[3-9]\d{9}"
                    >
                </div>
                <div>
                    <label class="block text-sm font-medium text-gray-700 mb-1">初始角色 <span class="text-danger">*</span></label>
                    <select
                            v-model="addUserForm.roleId"
                            class="input-style w-full"
                            required
                    >
                        <option value="">请选择角色</option>
                        <option v-for="role in roleList" :key="role.roleId" :value="role.roleId">
                            {{ role.roleName }}
                        </option>
                    </select>
                </div>

                <div class="flex justify-end space-x-3 pt-4 border-t border-gray-200">
                    <button type="button" class="btn-outline" @click="closeAddModal">取消</button>
                    <button type="submit" class="btn-primary">确认新增</button>
                </div>
            </form>
        </div>
    </div>

    <!-- 2. 分配角色弹窗 -->
    <div class="fixed top-0 left-0 right-0 bottom-0 flex items-center justify-center z-50" v-if="showAssignRoleModal">
        <div class="absolute inset-0 bg-black/50" @click="closeAssignRoleModal"></div>
        <div class="relative bg-white rounded-lg shadow-lg w-full max-w-lg mx-4">
            <div class="p-4 border-b border-gray-200 flex items-center justify-between">
                <h3 class="font-bold text-lg text-gray-700">分配角色 - {{ currentUser.username }}</h3>
                <button class="text-gray-400 hover:text-gray-700 transition-all-200" @click="closeAssignRoleModal">
                    <i class="fa fa-times"></i>
                </button>
            </div>
            <div class="p-6">
                <div class="mb-6">
                    <h4 class="text-sm font-medium text-gray-700 mb-3">当前用户角色</h4>
                    <div class="flex flex-wrap">
                            <span
                                    v-for="role in currentUser.roles"
                                    :key="role.roleId"
                                    class="inline-block px-3 py-1 text-sm rounded-full bg-gray-100 text-gray-700 mr-2 mb-2"
                            >
                                {{ role.roleName }}
                                <i class="fa fa-times ml-1 cursor-pointer hover:text-danger transition-all-200" @click="removeRole(role.roleId)"></i>
                            </span>
                        <span v-if="currentUser.roles.length === 0" class="text-gray-500 text-sm">未分配角色</span>
                    </div>
                </div>
                <div>
                    <h4 class="text-sm font-medium text-gray-700 mb-3">可选角色</h4>
                    <div class="grid grid-cols-1 md:grid-cols-2 gap-3">
                        <label
                                class="flex items-center p-3 border border-gray-200 rounded-md hover:bg-gray-50 transition-all-200 cursor-pointer"
                                v-for="role in roleList"
                                :key="role.roleId"
                                :class="assignedRoleIds.includes(role.roleId) ? 'bg-primary/5 border-primary/30' : ''"
                                @click="toggleRole(role.roleId)"
                        >
                            <input
                                    type="radio"
                                    :value="role.roleId"
                                    v-model="assignedRoleIds"
                                    class="h-4 w-4 text-primary border-gray-300 rounded"
                            >
                            <span class="ml-3 text-gray-700">{{ role.roleName }}</span>
                            <span class="ml-auto text-xs text-gray-400">{{ role.roleKey }}</span>
                        </label>
                    </div>
                </div>
                <div class="flex justify-end space-x-3 pt-6 border-t border-gray-200">
                    <button class="btn-outline" @click="closeAssignRoleModal">取消</button>
                    <button class="btn-primary" @click="handleAssignRole">确认分配</button>
                </div>
            </div>
        </div>
    </div>

    <!-- 3. 编辑用户弹窗 -->
    <div class="fixed top-0 left-0 right-0 bottom-0 flex items-center justify-center z-50" v-if="showEditModal">
        <div class="absolute inset-0 bg-black/50" @click="closeEditModal"></div>
        <div class="relative bg-white rounded-lg shadow-lg w-full max-w-md mx-4">
            <div class="p-4 border-b border-gray-200 flex items-center justify-between">
                <h3 class="font-bold text-lg text-gray-700">编辑用户 - {{ editUserForm.username }}</h3>
                <button class="text-gray-400 hover:text-gray-700 transition-all-200" @click="closeEditModal">
                    <i class="fa fa-times"></i>
                </button>
            </div>
            <form class="p-6 space-y-4" @submit.prevent="handleEditUser">
                <div>
                    <label class="block text-sm font-medium text-gray-700 mb-1">用户名</label>
                    <input
                            type="text"
                            v-model="editUserForm.username"
                            class="input-style w-full bg-gray-50 "
                    >
                </div>
                <div>
                    <label class="block text-sm font-medium text-gray-700 mb-1">手机号</label>
                    <input
                            type="tel"
                            v-model="editUserForm.phone"
                            placeholder="请输入手机号"
                            class="input-style w-full"
                            pattern="1[3-9]\d{9}"
                    >
                </div>

                <div>
                    <label class="block text-sm font-medium text-gray-700 mb-1">用户状态</label>
                    <select
                            v-model="editUserForm.status"
                            class="input-style w-full"
                    >
                        <option value="1">正常</option>
                        <option value="2">冻结</option>
                    </select>
                </div>



                <div class="flex justify-end space-x-3 pt-4 border-t border-gray-200">
                    <button type="button" class="btn-outline" @click="closeEditModal">取消</button>
                    <button type="submit" class="btn-primary">确认修改</button>
                </div>
            </form>
        </div>
    </div>
</div>

<script>
    new Vue({
        el: '#app',
        data() {
            return {
                // 侧边栏控制（移动端）
                sidebarShow: false,
                // 搜索表单
                searchForm: {
                    username: '',
                    phone: '',
                    status: '',
                    roleId: ''
                },
                // 用户列表数据（由后端接口填充）
                userList: [],
                totalCount: 0,
                currentPage: 1,
                pageSize: 10,
                // 角色列表（由后端接口填充）
                roleList: [],
                // 选中的用户ID（批量操作）
                selectedUserIds: [],
                selectAll: false,
                // 弹窗控制
                showAddModal: false,
                showEditModal: false,
                showAssignRoleModal: false,
                // 新增用户表单
                addUserForm: {
                    username: '',
                    password: '',
                    phone: '',
                    roleId: ''
                },
                // 编辑用户表单
                editUserForm: {
                    username: '',
                    phone: '',
                    status: ''
                },
                // 分配角色相关
                currentUser: {},
                assignedRoleIds: []
            }
        },
        computed: {
            // 总页数
            totalPages() {
                return Math.ceil(this.totalCount / this.pageSize);
            },
            // 分页页码范围（显示5个页码）
            pageRange() {
                const range = [];
                const total = this.totalPages;
                let start = Math.max(1, this.currentPage - 2);
                let end = Math.min(total, start + 4);
                if (end - start < 4) {
                    start = Math.max(1, end - 4);
                }
                for (let i = start; i <= end; i++) {
                    range.push(i);
                }
                return range;
            }
        },
        mounted() {
            // 初始化加载用户列表和角色列表
            this.fetchRoleList();
            this.fetchUserList();

            // 监听窗口大小变化（适配移动端）
            window.addEventListener('resize', this.handleResize);
        },
        beforeDestroy() {
            window.removeEventListener('resize', this.handleResize);
        },
        methods: {
            // 侧边栏切换（移动端）
            toggleSidebar() {
                this.sidebarShow = !this.sidebarShow;
                const overlay = document.querySelector('.overlay');
                overlay.classList.toggle('show');
            },
            // 窗口大小变化处理
            handleResize() {
                const isMobile = window.innerWidth <= 1023;
                const overlay = document.querySelector('.overlay');
                if (!isMobile) {
                    this.sidebarShow = false;
                    overlay.classList.remove('show');
                }
            },
            // 格式化时间（YYYY-MM-DD HH:mm:ss）
            formatTime(time) {
                if (!time) return '-';
                const date = new Date(time);
                return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')} ${String(date.getHours()).padStart(2, '0')}:${String(date.getMinutes()).padStart(2, '0')}:${String(date.getSeconds()).padStart(2, '0')}`;
            },
            // 获取用户列表（对接后端接口）
            fetchUserList() {
                axios.get('/user-role/selectAll', {
                    params: { ...this.searchForm, page: this.currentPage, size: this.pageSize }
                }).then(response => {
                    // 核心修改：对每个用户的角色信息进行格式转换
                    this.userList = response.data.records.map(user => {
                        return {
                            ...user, // 保留用户原有所有字段（id、username、phone等）
                            // 新增roles数组：若有roleId，则生成包含该角色的数组；否则为空数组
                            roles: user.roleId ? [
                                {
                                    roleId: user.roleId,
                                    roleName: user.roleName,
                                    roleKey: user.roleKey
                                }
                            ] : []
                        };
                    });
                    this.totalCount = response.data.total;
                }).catch(error => {
                    console.error('获取用户列表失败:', error);
                });
            },
            // 获取角色列表（对接后端接口）
            fetchRoleList() {
                // 实际项目中替换为后端接口请求
                axios.get('/role/getRoles')
                    .then(response => {
                        this.roleList = response.data;
                    }).catch(error => {
                    console.error('获取角色列表失败:', error);
                });
            },
            // 重置搜索条件
            resetSearch() {
                this.searchForm = {
                    username: '',
                    phone: '',
                    status: '',
                    roleId: ''
                };
                this.currentPage = 1;
            },
            // 全选/取消全选
            handleSelectAll() {
                if (this.selectAll) {
                    this.selectedUserIds = this.userList.map(user => user.id);
                } else {
                    this.selectedUserIds = [];
                }
            },
            // 批量冻结用户
            batchFreeze() {
                if (confirm(`确定要冻结选中的${this.selectedUserIds.length}个用户吗？`)) {
                    // 实际项目中替换为后端接口请求
                    axios.put('/users/batch-freeze', {
                        userIds: this.selectedUserIds
                    }).then(() => {
                        this.fetchUserList();
                        this.selectedUserIds = [];
                        this.selectAll = false;
                        alert('冻结成功');
                    }).catch(error => {
                        console.log(this.selectedUserIds)
                        console.error('批量冻结失败');
                        alert('冻结失败');
                    });
                }
            },
            // 批量删除用户
            batchDelete() {
                if (confirm(`确定要删除选中的${this.selectedUserIds.length}个用户吗？此操作不可恢复！`)) {
                    // 实际项目中替换为后端接口请求
                    axios.post('/users/batch-delete', {
                        userIds: this.selectedUserIds
                    }).then(() => {
                        this.fetchUserList();
                        this.selectedUserIds = [];
                        this.selectAll = false;
                        alert('删除成功');
                    }).catch(error => {
                        console.error('批量删除失败:', error);
                        alert('删除失败');
                    });
                }
            },
            // 冻结单个用户
            handleFreezeUser(userId) {
                if (confirm('确定要冻结此用户吗？')) {
                    // 实际项目中替换为后端接口请求
                    axios.get(`/users/freeze/${userId}`)
                        .then(() => {
                            this.fetchUserList();
                            alert('冻结成功');
                        }).catch(error => {
                        console.error('冻结用户失败:', error);
                        alert('冻结失败');
                    });
                }
            },
            // 解冻单个用户
            handleUnfreezeUser(userId) {
                if (confirm('确定要解冻此用户吗？')) {
                    // 实际项目中替换为后端接口请求
                    axios.get(`/users/fetchUser/${userId}`)
                        .then(() => {
                            this.fetchUserList();
                            alert('解冻成功');
                        }).catch(error => {
                        console.error('解冻用户失败:', error);
                        alert('解冻失败');
                    });
                }
            },
            // 显示新增用户弹窗
            showAddUserModal() {
                this.addUserForm = {
                    username: '',
                    password: '',
                    phone: '',
                    roleId: '',
                    balance: 0
                };
                this.showAddModal = true;
            },
            // 关闭新增用户弹窗
            closeAddModal() {
                this.showAddModal = false;
            },
            // 处理新增用户
            handleAddUser() {
                // 实际项目中替换为后端接口请求
                axios.post('/users/add', this.addUserForm)
                    .then(() => {
                        this.closeAddModal();
                        this.fetchUserList();
                        alert('新增用户成功');
                    }).catch(error => {
                    console.error('新增用户失败:', error);
                    alert('新增用户失败');
                });
            },
            // 显示编辑用户弹窗
            showEditUserModal(user) {
                // 深拷贝用户数据到编辑表单
                this.editUserForm = JSON.parse(JSON.stringify(user));
                // 转换余额单位（分 -> 元）
                // this.editUserForm.balance = (this.editUserForm.balance / 100).toFixed(2);
                this.showEditModal = true;
            },
            // 关闭编辑用户弹窗
            closeEditModal() {
                this.showEditModal = false;
            },
            // 处理编辑用户
            handleEditUser() {
                // 转换余额单位（元 -> 分）
                const formData = {
                    ...this.editUserForm
                };

                // 实际项目中替换为后端接口请求
                axios.put(`/users/${formData.id}`, formData)
                    .then(() => {
                        this.closeEditModal();
                        this.fetchUserList();
                        alert('编辑用户成功');
                    }).catch(error => {
                    console.error('编辑用户失败:', error);
                    alert('编辑用户失败');
                });
            },
            // 显示分配角色弹窗
            openAssignRoleModal(user) {
                console.log('打开分配角色弹窗', user);
                console.log('用户角色数据', user.roles);
                this.currentUser = JSON.parse(JSON.stringify(user));
                this.assignedRoleIds = user.roles.map(role => role.roleId);
                this.showAssignRoleModal = true;
                console.log('弹窗状态设置为', this.showAssignRoleModal);
            },
            // 关闭分配角色弹窗
            closeAssignRoleModal() {
                this.showAssignRoleModal = false;
            },
            // 切换角色选择状态
            toggleRole(roleId) {
                const index = this.assignedRoleIds.indexOf(roleId);
                if (index > -1) {
                    this.assignedRoleIds.splice(index, 1);
                } else {
                    this.assignedRoleIds.push(roleId);
                }
            },
            // 移除角色
            removeRole(roleId) {
                const index = this.assignedRoleIds.indexOf(roleId);
                if (index > -1) {
                    this.assignedRoleIds.splice(index, 1);
                }
            },
            // 处理角色分配
            handleAssignRole() {
                // 核心修改：从数组中取第一个角色ID（单角色场景），无角色则传null
                const roleId = this.assignedRoleIds.length > 0 ? this.assignedRoleIds[0] : null;

                axios.post(`/user-role/${this.currentUser.id}/assign-roles`, {
                    roleId: roleId // 传递单个roleId：1 或 null
                }).then(() => {
                    this.closeAssignRoleModal();
                    this.fetchUserList(); // 重新获取用户列表，更新角色信息
                    alert('角色分配成功');
                }).catch(error => {
                    console.error('角色分配失败:', error);
                    alert('角色分配失败');
                });
            }
        },
        watch: {
            // 监听用户列表变化，更新全选状态
            userList() {
                this.selectAll = this.userList.length > 0 &&
                    this.selectedUserIds.length === this.userList.length;
            },
            // 监听选中用户ID变化，更新全选状态
            selectedUserIds() {
                this.selectAll = this.userList.length > 0 &&
                    this.selectedUserIds.length === this.userList.length;
            },
            // 监听页码变化，加载对应页数据
            currentPage() {
                this.fetchUserList();
            }
        }
    });
</script>
</body>
</html>

